feat(plugin): add Dameng DM8 support - #2114
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d541700175
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // On DML error, send ROLLBACK to clean up connection state | ||
| if !has_result_set { | ||
| let _ = self.rollback(); | ||
| } |
There was a problem hiding this comment.
Keep explicit transactions active after statement errors
When a DML statement fails inside an explicit transaction, this path calls rollback(), which rolls back the whole transaction and resets auto_commit to true. If the caller catches the statement error and continues, the next successful write is therefore committed immediately, and a later explicit rollback cannot undo it; return the statement error without silently changing transaction state.
Useful? React with 👍 / 👎.
| // COMMIT may also invalidate the server-side statement handle. | ||
| // Reset to 0 so the next execute() will allocate a fresh one. | ||
| self.handle = 0; |
There was a problem hiding this comment.
Preserve the connection handle after commit
After an explicit commit, this clears self.handle, even though that field was populated from login_resp.session_id and is subsequently used by FETCH, LOB, and keepalive messages. A later result requiring fetch_more or LOB retrieval is then sent with handle 0 and can fail despite the client remaining in Ready; rollback repeats the same reset, so neither transaction completion path should discard the session handle.
Useful? React with 👍 / 👎.
| if let Ok(s) = std::str::from_utf8(data) { | ||
| if let Ok(d) = rust_decimal::Decimal::from_str(s.trim()) { | ||
| return Some(DmValue::Decimal(d)); |
There was a problem hiding this comment.
Preserve high-precision decimal values as text
For DECIMAL/NUMERIC values outside rust_decimal's 96-bit representable range, parsing the already textual value fails and the binary fallback also fails because it receives ASCII data. row.get consequently returns None, which the bridge converts to SQL NULL, silently corrupting displayed and exported high-precision values; keep the decoded decimal text instead of requiring it to fit rust_decimal.
Useful? React with 👍 / 👎.
d541700 to
7baa5e0
Compare
7baa5e0 to
07c7d40
Compare
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Review fixes pushed to this branchI ran a review pass over the driver, the Rust bridge, the C ABI, and the core registry changes, then pushed 5 commits on top of Data lossDecode failures became SQL NULL. Binary DECIMAL decoded with the wrong value. The fix was mostly deletion of a duplicate: Two related things fell out of that. The call site's Packed DATE, TIME and TIMESTAMP rendered as control characters. The arm returned View definitions were truncated then written back.
SQL injectionThe driver interpolates literals rather than binding parameters, so DM8 supports a MySQL compatible mode where backslash escapes inside string literals. The binder only doubled quotes, so a trailing backslash escaped its own closing quote. It now probes the server once at connect with Two things I found while fixing that are worth calling out, because they are subtle:
Row caps
I deleted the rewrite rather than patching it, because the cap is already enforced natively. While there, Connection lifecycle
Also: Explain planThe registry entry omitted The plan parser also derived tree depth from the spaces between the line number and CI
Verification
Each new test was checked to fail on the previous code, not just to pass on the new code. Two things I could not verify, and one for youI had no DM8 server, so the 2 integration cases skipped throughout.
I added the Happy to talk through any of these if you disagree with a call, particularly deleting |
Adds first-class Dameng DM8 support as a downloadable macOS database-driver plugin.
Preview
What you get
dm://URL scheme and browse or switch schemas without installing a local DM client.EXPLAINoutput in TablePro's visual plan view.Driver architecture and safety
The plugin uses Swift for TablePro integration, a documented C ABI for ownership boundaries, and a Rust native-wire bridge. The bridge vendors a pinned MIT-licensed
rust-damengsnapshot with compatibility fixes for multi-column results, DECIMAL values, empty result sets, bounded message reads, LOB limits, and DM8's text EXPLAIN response.Parameter substitution is SQL-state aware, escapes text values, and encodes binary values with
HEXTORAW. Native panics are contained at the C boundary, response and LOB allocations are capped, row limits stop after the requested cap plus a truncation sentinel, and unrecoverable protocol failures close the connection.Native TLS is not available yet; the documentation recommends SSH, SOCKS, or Cloudflare tunnels for untrusted networks. Native binary and off-row LOB reads remain documented limitations.
Tests
d5417001: all jobs passed.DamengDriverTests.xctestagainst DM8 in OrbStack: 6 tests passed, including schema/table/view metadata, empty foreign-key results, Unicode and binary values, row caps, EXPLAIN, transactions, invalid credentials, hostile inputs, and cleanup.swift test --package-path Packages/TableProCore: 181 tests passed.swiftlint lint --strict: clean.The aggregate TablePro test run reached unrelated existing failures and then stalled in
MCPBridgeIntegrationTests.BridgeHarness.startReader(); all DM8 and changed-area suites pass. SwiftFormat 0.62.1 cannot read the repository's existing legacy--ifdefindentoption.Closes #1671
Closes #2010
Related to #2003